iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 22
0

前提:便捷語符

便捷語符不代表他很便捷,(就跟老婆餅沒老婆一樣)。
它可透過一些特殊語符(符號+方法),達到某些功能。這往往會在不影響程式整體結構下來增加一些功能,其實就是AOP(剖面導向)的核心觀念。

  • 語法糖
    寫程式也能吸大麻?那就是語法糖的特色,目的是為了讓編程者和閱覽程式的人在開發上更加簡潔、方便。
  • 語法鹽
    指的是讓程式閱覽更加困難的語法,這種方法往往是故意造成的。目的為了要讓破解程式的人看不懂程式的語法和邏輯。
  • 語法糖精
    也是類似語法鹽,但他可能是不小心造成的。且對破解保護毫無幫助,只會對編程者更加不利。

剖面導向(AOP)的意義

之前介紹各種程式設計法時有談到 AOP是抽象的,而且理解它是有難度的,所以稍微感覺一下它就好了。
OOP的物件都是寫在代碼裡的,可以提高程式的穩定性。但AOP強調是插入或增加一些功能與語法,並且不改變原本的結構。

AOP用在測試 , 外部深入處理 , 寫入日誌檔 , 監控(包含HIPS入侵防禦系統),有很大幫助。

裝飾器

有人會把他歸類為函式設計的一部份,但它還是進入AOP前會用到的觀念。

  • @用法

這就需透過裝飾器@的用法了,有時函式調用不能改變其結構。因為其他物件也要調用同方法,這時"@"就相當方便了。它也是種語法糖,所以不影響原語法

有兩函式或class a 跟 b 並且a(b) 繼承
所以@a 就是 b = a(b)

@a要寫在兩物件中間,但a(b)要寫後面。這就產生了功能差別

import time
def timeit(foo):
    def fc():
        start = time.clock()
        a = int(input('range?'))
        foo(a)  #插入功能
        end =time.clock()
        print('used:' , end-start)
    return fc
@timeit
def foo(a):
    for i in range(0,a):
        i+=1
        print('%d range' %i)    
timeit(foo())

有發現嗎?這樣隨時變更foo(a)功能就不會跟其他方法衝突了

  • cls跟self

這兩個可通稱為靜態類別,都是為了定義方法給物件以便於使用。

self:專門用在OOP,會被__init__先調用
cls :專門用在AOP,會被class先調用

來看以下內建裝飾器與cls的用法:

class AR(object): 
    @staticmethod    #不須再把類別物件化:AR=AR() 
    def a():         #包含靜態類別 
        print('fc_a')
    @classmethod     #不須再把類別物件化:AR=AR()
    def wd(cls):     #須有靜態類別 cls
        return ('fc_wd')

AR.a()  
AR.wd()

這語法糖可謂二度減化語法,達到簡潔的特性。
這裡的cls是為class提拱參考屬性用的,這樣才可直接當成物件調用

複雜型@用法

@為何可代替 b = b(a) 呢?那是因為它的靈活性:

def M(name):
    def M_ins(func):
        def M_fc1(*args):
            print(name)
            print("i'm M_fc1 empty")
            a = func(*args)
            print("i'm M_fc1 fc")
            return a
        return M_fc1
    return M_ins
#可延續 可改值
@M('dc1')
def dc1(name):
    print(name)
    return None
@M('dc2')
def dc2(name):
    print(name)
    return None

dc1('name1')
dc2('name2')

以前可能需透過OOP的多重繼承才能做到的複雜調用,現在透過裝飾器也能做到這點。

而它也可以疊加方法,但為了避免改變方法。需額外做個為裝飾器調用之物件,這樣才不會影響主結構
就算沒做額外物件,裝飾器也會避免方法影響程式結構。所以可透過特性來檢查裝飾器是否可工作。

def fc1(func):
    def infc(r):
        print('fc1')
        r = func(r)  # 避免影響功能的調用
        return r
    return infc
def fc2(func):
    def infc(r):
        print('fc2')
        r = func(r)  # 避免影響功能的調用
        return r
    return infc
def fc3(func):
    def infc(r):
        print('fc3')
        r = func(r)  # 避免影響功能的調用
        return r
    return infc
#test = fc1(fc2(fc3(test)))
@fc1
@fc2
@fc3
def test(name):
    print(name)

test('test')

上一篇
[D21] python遞迴
下一篇
[D23] 裝飾器2 + 入門AOP
系列文
從寫程式到脫離菜雞的歷練(以python為主的資處與檔案權限)32
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言